$.fn.extend({
    jsonColorful : function(to = false){
    	let jsonStr = this.text();
    	let jsonObj = JSON.parse(jsonStr);
    	let type = this._getDataRealType(jsonObj);
    	if(jsonObj){
    		if(to){
	    		to.html(this._renderJsonColorful(jsonObj))
    		}else{
	    		this.html(this._renderJsonColorful(jsonObj))
    		}
    	}
    	return this;
    },
    _renderJsonColorful: function(json, deep = 1, key = 1, lenght = 1){
    	type = this._getDataRealType(json);
        let prefix = '&ensp;'.repeat(deep*4);
        let suffix = '&ensp;'.repeat((deep-1)*4);
        let i = 1, html = '';
        let that = this;
        if(type == 'object'){
            html += '{<span class="toggle-container"><br>'
            let len = Object.keys(json).length
            $.each(json, function(idx, val){
            	let valType = that._getDataRealType(val);
            	if($.inArray(valType, ['object', 'array'])!= -1) {
            		html += that._genDataToggleHtml();
            		prefix = '&ensp;'.repeat(deep*4 - 2);
            	}
                html += prefix + that._genIdxHtml(idx)
                html += that._renderJsonColorful(val, deep + 1, i, len)
                i += 1;
            });
            html += suffix + '</span>}'
        }else if(type == 'array'){
            html += '[<span class="toggle-container"><br>'
            $.each(json, function(idx, val){
                html += prefix
                html += that._renderJsonColorful(val, deep + 1, i, json.length)
                i += 1;
            });
            html += suffix + '</span>]'
        }else{
            html += this._genValHtml(json, type);
        }
        if( key != lenght ){
            html += ',';
        }
        html += '<br>';
        return html;
    },
    _getDataRealType: function(dat){
        let str = toString.call(dat);
        let type = str.split(' ')[1];
        type = type.substr(0, type.length - 1).toLowerCase();
        return type;
    },
    _JSON_COLOR_CONST : {
	    MINUS : '<i class="fa fa-minus-square-o" aria-hidden="true"></i>',
	    PLUS : '<i class="fa fa-plus-square-o" aria-hidden="true"></i>',
	    TAB : '&ensp;'
    },
    _genIdxHtml: function(name){
        return '<span class="PropertyName">"' + name + '"</span><span class="colon">:&ensp;</span>';
    },
    _genValHtml: function(name, type){
        let string = "";
        if(type == 'string') string = '"';
        return '<span class="type-' + type + '">' + string + name + string + '</span>';
    },
    _genDataToggleHtml(){
        return ret = '<span class="json-toggle">'+this._JSON_COLOR_CONST.MINUS+'&ensp;</span>';
    }
});
$(function(){
	$('.json-toggle').on('click', function(){
		let $i = $(this).children('i');
		if($i.hasClass('fa-plus-square-o')){
			$i.addClass('fa-minus-square-o');
			$i.removeClass('fa-plus-square-o');
		}else{
			$i.addClass('fa-plus-square-o');
			$i.removeClass('fa-plus-minus-o');
		}
		$(this).next().next().next().toggle()
	});
})